package com.rykj.energy.database.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.rykj.energy.common.dto.CameraDto;
import com.rykj.energy.common.enums.DeviceTypes;
import com.rykj.energy.common.enums.ExceptionCode;
import com.rykj.energy.common.enums.StateType;
import com.rykj.energy.common.utils.*;
import com.rykj.energy.database.mapper.CameraMapper;
import com.rykj.energy.database.pojo.BasicCamera;
import com.rykj.energy.database.pojo.BasicCameraPresetting;
import com.rykj.energy.database.pojo.vo.DeviceVo;
import com.rykj.energy.database.service.ICameraPresettingService;
import com.rykj.energy.database.service.ICameraService;
import lombok.extern.slf4j.Slf4j;
import net.anumbrella.seaweedfs.core.FileTemplate;
import net.anumbrella.seaweedfs.core.file.FileHandleStatus;
import org.quartz.JobDataMap;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileInputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service("cameraService")
@Slf4j
public class CameraServiceImpl implements ICameraService {

    @Autowired
    private CameraMapper cameraMapper;
    @Autowired
    private ICameraPresettingService cameraPresetService;

    //摄像头预置点操作接口
    private static String SDK_PRESET_POINT ="/camera-operation/sdk-preset-point";

    @Value("${file.upload:/data/rykj-energy/images}")
    private String savePicturePath;

    @Value("${ffmpeg.exe.path:ffmpeg}")
    private String ffmpegExePath;

    @Value("${point.sdk.url:http://127.0.0.1:8080}")
    private String pointSdkUrl;

    @Autowired
    @Lazy
    private FileTemplate template;

    @Override
    public void getVoToCamera(DeviceVo deviceVo, BasicCamera camera) {
        camera.setCamAlias(deviceVo.getDevAlias());
        camera.setCamBrands(deviceVo.getDevBrand());
        camera.setCamIndex(deviceVo.getDevChannelNum());
        camera.setCamIp(deviceVo.getDevIp());
        camera.setCamModel(deviceVo.getDevModel());
        camera.setCamNo(deviceVo.getDevNo());
        camera.setCamPort(deviceVo.getDevPort());
        camera.setCamPwd(deviceVo.getDevPwd());
        camera.setCamType(deviceVo.getCamType());
        camera.setCamUser(deviceVo.getDevUser());
        camera.setDevType(deviceVo.getDevType());
        camera.setOrgId(deviceVo.getOrgId());
        camera.setRtspUrl(deviceVo.getRtspUrl());
        camera.setId(deviceVo.getId());
        camera.setRtspPort(deviceVo.getRtspPort());
        //camera.setPhotoPath()
        camera.setRemark(deviceVo.getRemark());
    }

    @Override
    public Result checkCamera(BasicCamera camera) {
        if(!StringUtils.isIP(camera.getCamIp())){
            return Result.failure( ExceptionCode.DATA_ERROR.getMessage()+":"+camera.getCamIp());
        }
        //验证名称唯一
        if(StringUtils.isNotEmpty(camera.getCamAlias())){
            List<BasicCamera> cameras = findByChannelAlias(camera.getCamAlias());
            if(CollectionUtils.isNotEmpty(cameras)&&
                    (camera.getId()<1 || cameras.size()>1|| !(cameras.get(0).getId()+"").equals(camera.getId()+""))){
                return Result.failure( ExceptionCode.CAMERA_NAME_IS_EXISTENCE.getMessage());
            }
        }
        List<BasicCamera> cameras = null;
        cameras=  findByIpAndChannelIndex(camera.getCamIp(),camera.getCamIndex());
        if(CollectionUtils.isNotEmpty(cameras)&&
                (camera.getId()<1 || cameras.size()>1|| !(cameras.get(0).getId()+"").equals(camera.getId()+""))){
            return Result.failure(ExceptionCode.CAMERA_IS_EXISTENCE.getMessage());
        }

        if("RTSP".equals(camera.getDevType())){
            cameras = findByRtspUrl(camera.getRtspUrl());
            if(CollectionUtils.isNotEmpty(cameras)&&
                    (camera.getId()<1 || cameras.size()>1|| !(cameras.get(0).getId()+"").equals(camera.getId()+""))){
                return Result.failure( ExceptionCode.RTSPURL_IS_EXISTENCE.getMessage());
            }
        }
        return  Result.success("校验通过");
    }

    @Override
    public BasicCamera addCamera(BasicCamera camera, List<BasicCameraPresetting> cameraPresets) throws Exception {
        if(DeviceTypes.RTSP.getCode().equals(camera.getDevType())){
            camera.setCamIndex(0);
        }else if(StringUtils.isEmpty(camera.getCamIndex())){
            camera.setCamIndex(1);
        }
        if(StringUtils.isEmpty(camera.getCamBrands())){
            camera.setCamBrands("hk");
        }
        camera.setStatus(StateType.NORMAL.getCode());
        camera.setLineStatus(StateType.NORMAL.getCode());
        camera.setCreateTime(new Date());
        //ffmpeg抓图
        //if(StringUtils.isNotEmpty(ffmpegExePath)){
        FileHandleStatus fileHandle = getCameraImg(camera);
        if(null==fileHandle){
            throw new Exception("抓取现场画面失败");
        }
        camera.setPhotoPath(fileHandle.getFileUrl());

        try {
            cameraMapper.insert(camera);
            if(CollectionUtils.isNotEmpty(cameraPresets)){
                for (BasicCameraPresetting cameraPreset: cameraPresets) {
                    cameraPreset.setCameraId(camera.getId());
                    if(sdkPresetPoint(cameraPreset.getCameraNo(),cameraPreset.getPresettingCode())){
                        //抓取预置位现场画面
                        fileHandle = getCameraImg(camera);
                        if(null==fileHandle){
                            throw new Exception("通道id"+cameraPreset.getCameraNo()+"_预置点编号:"+cameraPreset.getPresettingCode()+" 抓取现场画面失败");
                        }
                        cameraPreset.setPreImgPath(fileHandle.getFileUrl());
                    }else {
                        log.error("通道id"+cameraPreset.getCameraNo()+"_预置点编号:"+cameraPreset.getPresettingCode()+" 操作失败");
                        //throw new Exception("通道id"+cameraPreset.getCameraNo()+"_预置点编号:"+cameraPreset.getPresettingCode()+" 操作失败");
                    }
                    cameraPresetService.saveCameraPreset(cameraPreset);
                }
            }
        }catch (Exception e){
            log.error("===新增摄像头异常===",e);
            throw new Exception("新增摄像头异常");
        }
        return camera;
    }

    @Override
    public List<BasicCamera> findByIp(String devIp) {
        Map<String, Object> columnMap = new HashMap<>();
        columnMap.put("camIp",devIp);
        columnMap.put("status", StateType.NORMAL.getCode());
        return cameraMapper.selectByMap(columnMap);
    }

    @Override
    public FileHandleStatus getCameraImg(BasicCamera camera) throws Exception {

        CameraDto cameraDto = new CameraDto();
        cameraDto.setCamBrands(camera.getCamBrands());
        cameraDto.setChannelIndex(camera.getCamIndex());
        cameraDto.setDevAddress(camera.getCamIp());
        cameraDto.setDevPort(camera.getRtspPort()==null?camera.getCamPort():camera.getRtspPort());
        cameraDto.setDevUser(camera.getCamUser());
        cameraDto.setDevPwd(camera.getCamPwd());
        cameraDto.setDevType(camera.getDevType());
        cameraDto.setRtspUrl(camera.getRtspUrl());
        String rtspUrl=FFmpegUtils.getRtsp(cameraDto);
        log.info("摄像头RTSP地址={}",rtspUrl);
        String picName = ShortUUID.generateShortUuid()+System.currentTimeMillis()+".jpg";
        FileHandleStatus fileHandle =null;
        String picPath=savePicturePath + File.separator + DateUtils.getDateToDay(new Date()) + File.separator + "camera";
        String picPathName=picPath + File.separator + picName;
        FFmpegUtils.getCaptureByRtsp(ffmpegExePath,rtspUrl,picPath,picName);
        File file = new File(picPathName);
        fileHandle = template.saveFileByStream(picName, new FileInputStream(file));
        //调用海康接口 获取最新摄像头抓怕图片

        log.info("===上传文件服务器返回结果==="+ JSONObject.toJSONString(fileHandle));
        return fileHandle;
    }

    @Override
    public List<BasicCamera> findByIpAndChannelIndex(String camIp, Integer camIndex) {
        Map<String, Object> columnMap = new HashMap<>();
        columnMap.put("camIp",camIp);
        columnMap.put("camIndex",camIndex);
        columnMap.put("status",StateType.NORMAL.getCode());
        return cameraMapper.selectByMap(columnMap);
        // return cameraRepository.findByIpAndChannelIndex(devAddress, channelIndex,TaskStatus.NORMAL.getValue());
    }
    @Override
    public List<BasicCamera> findByChannelAlias(String camAlias) {
        Map<String, Object> columnMap = new HashMap<>();
        columnMap.put("camAlias",camAlias);
        columnMap.put("status",StateType.NORMAL.getCode());
        return cameraMapper.selectByMap(columnMap);
    }

    @Override
    public List<BasicCamera> findByRtspUrl(String rtspUrl){
        Map<String, Object> columnMap = new HashMap<>();
        columnMap.put("rtspUrl",rtspUrl);
        columnMap.put("status",StateType.NORMAL.getCode());
        return cameraMapper.selectByMap(columnMap);
    }

    @Override
    public void deleteByDevId(Integer devId) {
        cameraMapper.deleteByDevId(devId);
    }

    @Override
    public void saveCameras(List<BasicCamera> cameras) throws Exception {
        try {
            cameras.forEach(r -> {
                if (StringUtils.isEmpty(r.getCamBrands())) {
                    r.setCamBrands("hk");
                }
                r.setStatus(StateType.NORMAL.getCode());
                r.setCreateTime(new Date());
                r.setLineStatus(StateType.NORMAL.getCode());
                cameraMapper.insert(r);
            });
        }catch (Exception e){
            log.error("===批量保存摄像头事失败===",e);
            throw new Exception("批量保存摄像头事失败");
        }
    }

    @Override
    public void deleteCamera(Integer cameraId) throws Exception {
        try {
            BasicCamera info = cameraMapper.selectById(cameraId);
            info.setStatus(StateType.DELETED.getCode());
            cameraMapper.updateById(info);
        }catch (Exception e){
            log.error("===删除摄像头异常===",e);
            throw new Exception("删除摄像头异常");
        }
    }

    @Override
    public void updateCamera(BasicCamera camera,List<BasicCameraPresetting> cameraPresets) throws Exception {

        BasicCamera cameraInfo = cameraMapper.selectById(camera.getId());
        BeanUtils.copyProperties(camera,cameraInfo);
        try{
            FileHandleStatus fileHandle = getCameraImg(cameraInfo);
            if(null==fileHandle){
                throw  new Exception("摄像头抓取现场图片异常");
            }
            cameraInfo.setLineStatus(StateType.NORMAL.getCode());
            cameraInfo.setPhotoPath(fileHandle.getFileUrl());
            cameraMapper.updateById(cameraInfo);
            if(CollectionUtils.isNotEmpty(cameraPresets)){
                for (BasicCameraPresetting cameraPreset:cameraPresets) {
                    cameraPreset.setCameraId(cameraInfo.getId());
                    if(sdkPresetPoint(cameraPreset.getCameraNo(),cameraPreset.getPresettingCode())){
                        //抓取预置位现场画面
                        fileHandle = getCameraImg(camera);
                        if(null==fileHandle){
                            throw new Exception("通道id"+cameraPreset.getCameraNo()+"_预置点编号:"+cameraPreset.getPresettingCode()+" 抓取现场画面失败");
                        }
                        cameraPreset.setPreImgPath(fileHandle.getFileUrl());
                    }else {
                        log.error("通道id"+cameraPreset.getCameraNo()+"_预置点编号:"+cameraPreset.getPresettingCode()+" 操作失败");
                        //throw new Exception("通道id"+cameraPreset.getCameraNo()+"_预置点编号:"+cameraPreset.getPresettingCode()+" 操作失败");
                    }
                    //抓取预置位现场画面
                    // cameraPreset.setPreImgPath();
                    if(StringUtils.isEmpty(cameraPreset.getId())||cameraPreset.getId()==0){
                        cameraPresetService.saveCameraPreset(cameraPreset);
                    }else {
                        cameraPresetService.updateCameraPreset(cameraPreset);
                    }
                }
            }
        }catch (Exception e){
            log.error("===修改摄像头异常===",e);
            cameraInfo.setLineStatus(StateType.OFFLINE.getCode());
            cameraMapper.updateById(cameraInfo);
            throw new Exception("修改摄像头异常");
        }
    }

    @Override
    public BasicCamera findById(Integer cameraId) {
        return cameraMapper.selectById(cameraId);
    }

    @Override
    public void updateCameraLineStatus(BasicCamera camera) {
        try {
            FileHandleStatus fileHandle = getCameraImg(camera);
            camera.setPhotoPath(fileHandle.getFileUrl());
            camera.setLineStatus(StateType.NORMAL.getCode());
//            List<BasicMeter> meters = meterService.getMetersByCameraId(camera.getId());
//            if(CollectionUtils.isNotEmpty(meters)){
//                for (BasicMeter m :meters  ) {
//                    m.setMeterImgUrl(camera.getPhotoPath());
//                    if(StringUtils.isNotEmpty(m.getRectSeat())){
//                        m.setMeterImgUrl( meterService.cutImgByRectSeat(camera.getPhotoPath(),m.getDistType(),m.getRectSeat()));
//                    }
//                    meterService.updateMeter(m);
//                }
//            }
        }catch (Exception e){
            log.error("====更新摄像头==="+camera.getCamAlias()+"==在线状态异常=",e);
            camera.setLineStatus(StateType.OFFLINE.getCode());
        }
        cameraMapper.updateById(camera);
    }

    @Override
    public List<BasicCamera> getAllCameras() {
        Map<String,Object> comMap =new HashMap<>();
        comMap.put("status",StateType.NORMAL.getCode());
        return cameraMapper.selectByMap(comMap);
    }

    @Override
    public BasicCamera getCameraByCluster(String cameraId) {
        String cameraIps[] =cameraId.split("_");
        if(cameraIps.length<3){
            return null;
        }
        String ipAddress=cameraIps[0];
        String port = cameraIps[1];
        String channelIndex = cameraIps[2];
        String devType = null;
        if(cameraId.contains("rtsp")){
            devType ="RTSP";
            ipAddress = ipAddress.substring(4,ipAddress.length());
        }
        return cameraMapper.getOneByAddressAndType(ipAddress,Integer.valueOf(channelIndex),devType,port);
    }

    @Override
    public BasicCamera findInfoByCameraNo(String cameraNo) {
        return cameraMapper.findByCamNo(cameraNo);
    }

    @Override
    public boolean sdkPresetPoint(String cameraNo, Integer code) throws Exception {
        boolean flag=false;
        if("http://127.0.0.1:8080".equals(pointSdkUrl)){
            return flag;
        }
        String pointUrl =pointSdkUrl+SDK_PRESET_POINT;
        JSONObject colm=new JSONObject();
        colm.put("cameraNo",cameraNo);
        colm.put("code",code);
        String result= HttpClientUtils.post(pointUrl,JSONObject.toJSONString(colm));
        log.info("===预置点操作返回结果=="+result);
        JSONObject resultObj=JSONObject.parseObject(result);

        if(resultObj!=null &&  null!=resultObj.get("header") && "0".equals(resultObj.getJSONObject("header").getString("code")) ){
            flag=true;
        }
        return flag;
    }

    @Override
    public String saveRtspUrlByCameraInfo(BasicCamera camera) {
        CameraDto cameraDto = new CameraDto();
        cameraDto.setCamBrands(camera.getCamBrands());
        cameraDto.setChannelIndex(camera.getCamIndex());
        cameraDto.setDevAddress(camera.getCamIp());
        cameraDto.setDevPort(StringUtils.isEmpty(camera.getRtspPort())? camera.getCamPort():camera.getRtspPort());
        cameraDto.setDevUser(camera.getCamUser());
        cameraDto.setDevPwd(camera.getCamPwd());
        cameraDto.setDevType(camera.getDevType());
        cameraDto.setRtspUrl(camera.getRtspUrl());
        camera.setRtspUrl( FFmpegUtils.getRtsp(cameraDto));
        cameraMapper.updateById(camera);
        return camera.getRtspUrl();
    }


}
